package org.hamster.common.puremvc.mediator
{
	import flash.events.IEventDispatcher;
	
	import mx.collections.ArrayCollection;
	
	import org.hamster.common.manager.pointcut.PointcutManager;
	import org.hamster.common.manager.pointcut.events.PointcutEvent;
	import org.hamster.common.manager.pointcut.vo.PointcutVO;
	import org.hamster.common.puremvc.constants.PointcutTiming;
	import org.puremvc.as3.interfaces.INotification;
	import org.puremvc.as3.patterns.mediator.Mediator;
	
	import spark.collections.Sort;
	import spark.collections.SortField;
	
	public class BaseMediator extends Mediator
	{
		private var _viewStatus:uint = 0x0;
		
		public function set viewStatus(value:uint):void
		{
			if (_viewStatus != value) {
				_viewStatus = value;
				statusChanged();
			}
		}
		
		public function get viewStatus():uint
		{
			return _viewStatus;
		}
		
		
		public function BaseMediator(mediatorName:String=null, viewComponent:Object=null)
		{
			super(mediatorName, viewComponent);
		}
		
		override public function handleNotification(notification:INotification):void
		{
			var name:String = notification.getName();
			var body:Object = notification.getBody();
			var handler:String = getNotiHandlerName(name);
			
			if (this.hasOwnProperty(handler)) {
				var func:Function = this[handler];
				func.apply(this, [body]);
			} else {
				trace (this.mediatorName + ":" + name + "received but no handler found!");
			}
		}
		
		public function getNotiHandlerName(notiName:String):String
		{
			return "handle" + notiName.substr(0, 1).toLocaleUpperCase() + notiName.substr(1);
		}
		
		public function setStatus(statusKey:uint):void
		{
			viewStatus = statusKey;
			this.statusChanged();
		}
			
		
		public function isStatusAvailable(statusKey:uint):Boolean
		{
			return (statusKey & viewStatus) == statusKey;
		}
		
		public function setStatusAvailable(statusKey:uint, available:Boolean):void
		{
			viewStatus = viewStatus | statusKey;
			
			if (!available) {
				viewStatus = viewStatus ^ statusKey;
			}
			
			statusChanged();
		}
		
		protected function statusChanged():void
		{
			
		}
		
		protected var pointcutManager:PointcutManager = new PointcutManager();
		
		override public function sendNotification(notificationName:String, body:Object=null, type:String=null):void
		{
			var pcManager:PointcutManager = this.pointcutManager.clone();
			
			if (pcManager.hasPointcut(notificationName, PointcutTiming.BEFORE_SEND)) {
				pcManager.data = addCache(notificationName, body, type);
				pcManager.addEventListener(PointcutEvent.POINTCUT_FINISH, pcFinishBeforeSendHandler);
				pcManager.addEventListener(PointcutEvent.POINTCUT_CANCEL, pcCancelBeforeSendHandler);
				pcManager.executePointcuts(notificationName, PointcutTiming.BEFORE_SEND);
				return;
			}
			
			super.sendNotification(notificationName, body, type);
			
			if (pcManager.hasPointcut(notificationName, PointcutTiming.AFTER_SEND)) {
				pcManager.data = addCache(notificationName, body, type);
				pcManager.addEventListener(PointcutEvent.POINTCUT_FINISH, pcFinishAfterSendHandler);
				pcManager.addEventListener(PointcutEvent.POINTCUT_CANCEL, pcCancelAfterSendHandler);
				pcManager.executePointcuts(notificationName, PointcutTiming.AFTER_SEND);
			}
		}
		
		protected function pcFinishBeforeSendHandler(event:PointcutEvent):void
		{
			var pcManager:PointcutManager = event.currentTarget as PointcutManager;
			pcManager.removeEventListener(PointcutEvent.POINTCUT_FINISH, pcFinishBeforeSendHandler);
			pcManager.removeEventListener(PointcutEvent.POINTCUT_CANCEL, pcFinishBeforeSendHandler);
			
			var cache:BaseMediatorPointcutCache = pcManager.data as BaseMediatorPointcutCache;
			super.sendNotification(cache.notificationName, cache.body, cache.type);
			
			if (pcManager.hasPointcut(cache.notificationName, PointcutTiming.AFTER_SEND)) {
				pcManager.addEventListener(PointcutEvent.POINTCUT_FINISH, pcFinishAfterSendHandler);
				pcManager.addEventListener(PointcutEvent.POINTCUT_CANCEL, pcCancelAfterSendHandler);
				pcManager.executePointcuts(cache.notificationName, PointcutTiming.AFTER_SEND);
			}
		}
		
		protected function pcCancelBeforeSendHandler(event:PointcutEvent):void
		{
			var pcManager:PointcutManager = event.currentTarget as PointcutManager;
			pcManager.removeEventListener(PointcutEvent.POINTCUT_FINISH, pcFinishBeforeSendHandler);
			pcManager.removeEventListener(PointcutEvent.POINTCUT_CANCEL, pcFinishBeforeSendHandler);
		}
		
		protected function pcFinishAfterSendHandler(event:PointcutEvent):void
		{
			var pcManager:PointcutManager = event.currentTarget as PointcutManager;
			pcManager.removeEventListener(PointcutEvent.POINTCUT_FINISH, pcFinishAfterSendHandler);
			pcManager.removeEventListener(PointcutEvent.POINTCUT_CANCEL, pcCancelAfterSendHandler);
		}
		
		protected function pcCancelAfterSendHandler(event:PointcutEvent):void
		{
			var pcManager:PointcutManager = event.currentTarget as PointcutManager;
			pcManager.removeEventListener(PointcutEvent.POINTCUT_FINISH, pcFinishAfterSendHandler);
			pcManager.removeEventListener(PointcutEvent.POINTCUT_CANCEL, pcCancelAfterSendHandler);
		}
		
		private function addCache(notificationName:String, body:Object, type:String):BaseMediatorPointcutCache
		{
			var cache:BaseMediatorPointcutCache = new BaseMediatorPointcutCache();
			cache.notificationName = notificationName;
			cache.body = body;
			cache.type = type;
			return cache;
		}
		
		
	}
}